package cn.graydove.bot.core;

import cn.graydove.bot.adapter.GroupMessageEvent;
import cn.graydove.bot.data.GroupServiceCacheData;
import cn.graydove.bot.model.entity.Administrator;
import cn.graydove.bot.model.entity.QqGroup;
import cn.graydove.bot.support.BotProperties;
import cn.graydove.bot.utils.CommonUtils;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;

@Component
public class Assert {

    private GroupServiceCacheData groupServiceCacheData;

    private BotProperties botProperties;

    public Assert(GroupServiceCacheData groupServiceCacheData, BotProperties botProperties) {
        this.groupServiceCacheData = groupServiceCacheData;
        this.botProperties = botProperties;
    }

    public AssertBuilder builder(GroupMessageEvent event) {
        return new AssertBuilder(event, groupServiceCacheData, botProperties);
    }

    public void groupReceive(GroupMessageEvent event, Consumer<QqGroup> consumer) {
        builder(event).isGroup().isAlive().accept(consumer);
    }

    public void groupAdminReceive(GroupMessageEvent event, Consumer<QqGroup> consumer) {
        builder(event).isGroup().isAlive().isAdmin().accept(consumer);
    }

    public void groupHostReceive(GroupMessageEvent event, Consumer<QqGroup> consumer) {
        builder(event).isGroup().isAlive().isHost().accept(consumer);
    }

    public static class AssertBuilder {
        BotProperties botProperties;
        GroupMessageEvent event;
        QqGroup group;
        boolean ans = true;

        AssertBuilder(GroupMessageEvent event, GroupServiceCacheData groupServiceCacheData, BotProperties botProperties) {
            this.event = event;
            this.group = groupServiceCacheData.ensureUserAndGetGroup(event);
            this.botProperties = botProperties;
        }

        public AssertBuilder isAdmin() {
            ans = ans && (
                    CommonUtils.in(event.getUserId(), group.getAdministrator(), Administrator::getQqNumber) ||
                    Objects.equals(event.getUserId(), group.getHost().getQqNumber()) ||
                    Objects.equals(event.getUserId(), botProperties.getHostQq())
                );
            return this;
        }

        public AssertBuilder isHost() {
            ans = ans && (
                    Objects.equals(event.getUserId(), group.getHost().getQqNumber()) ||
                    Objects.equals(event.getUserId(), botProperties.getHostQq())
                );
            return this;
        }

        public AssertBuilder isGroup() {
            ans = ans && (group != null);
            return this;
        }

        public AssertBuilder assertTrue(Supplier<Boolean> supplier) {
            ans = ans && supplier.get();
            return this;
        }

        public AssertBuilder assertFalse(Supplier<Boolean> supplier) {
            ans = ans && !supplier.get();
            return this;
        }

        public AssertBuilder isAlive() {
            ans = ans && group.getAlive();
            return this;
        }

        public AssertBuilder isNotAlive() {
            ans = ans && !group.getAlive();
            return this;
        }

        public void accept(Consumer<QqGroup> consumer) {
            if (ans) {
                consumer.accept(group);
            }
        }

        public void deny(Consumer<QqGroup> consumer) {
            if (!ans) {
                consumer.accept(group);
            }
        }
    }
}
